package edu.mbb.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;

public class NettyService {
	// 在Nio中 需要 有channl 通道 连接到主线程的中 就是accpet监听的不在是直接的请求而是在 channel中的 请求
	// 而请求直接到了是channel 而不是accpet 体现了是 多路复用的 原则。
	// 而在 NIO中当 监听到请求后，做的事情是 把绑定监听地址 到IneetSocketAddress
	// 创建对应的Selector 启动线程
	// 而 Selector 就会轮询就绪的key
	// 此时异步（NIO的核心部分） 监听 读操作，异步读消息到 ByteBuffer中，
	// 同时 也异步的写消息到 ByteBuffer 到SocketChannel
	public static void main(String[] args) throws InterruptedException {
		ServerBootstrap serverBootstrap = new ServerBootstrap();
		NioEventLoopGroup boos = new NioEventLoopGroup();
		NioEventLoopGroup work = new NioEventLoopGroup();
		serverBootstrap.group(boos, work).channel(NioServerSocketChannel.class)
				.childHandler(new ChannelInitializer<SocketChannel>() {

					@Override
					protected void initChannel(SocketChannel ch) throws Exception {
						// 用于解决半包问题
						ch.pipeline().addLast("frameDecoder",
								new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
						ch.pipeline().addLast("frameEncoder", new LengthFieldPrepender(4));
						ch.pipeline().addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
						ch.pipeline().addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
						ch.pipeline().addLast(new RpcServerHandler());
					}

				}).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);
		String ip = "127.0.0.1";
		int port = 8098;
		ChannelFuture sync = serverBootstrap.bind(ip, port).sync();
		System.out.println("服务已经启动");
		sync.channel().closeFuture().sync();
	}

}
